package com.health.system.javacommon.base;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.dao.support.DaoSupport;
import org.springframework.orm.ibatis.SqlMapClientCallback;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.util.Assert;


import com.ibatis.sqlmap.client.SqlMapExecutor;

import cn.org.rapid_framework.beanutils.BeanUtils;
import cn.org.rapid_framework.page.Page;
import cn.org.rapid_framework.page.PageRequest;

/**
 * @author badqiu
 * @version 1.0
 */
public abstract class BaseIbatis3Dao<E, PK extends Serializable> extends
		DaoSupport implements EntityDao<E, PK> {
	protected final Log log = LogFactory.getLog(getClass());

	private SqlSessionFactory sqlSessionFactory;
	private SqlSessionTemplate sqlSessionTemplate;
	private SqlMapClientTemplate sqlMapClientTemplate;

	private  int seq = 10;    //搴忓垪,鍙栧�鑼冨洿浠�0鍒�9锛� 鐢ㄤ簬浜х敓浠诲姟ID

	public SqlMapClientTemplate getSqlMapClientTemplate() {
		return sqlMapClientTemplate;
	}

	public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) {
		this.sqlMapClientTemplate = sqlMapClientTemplate;
	}

	protected void checkDaoConfig() throws IllegalArgumentException {
		Assert.notNull("sqlSessionFactory must be not null");
	}

	public SqlSessionFactory getSqlSessionFactory() {
		return sqlSessionFactory;
	}

	public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
		this.sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
	}

	public abstract Class getEntityClass();

	public SqlSessionTemplate getSqlSessionTemplate() {
		return sqlSessionTemplate;
	}

	public Object getById(PK primaryKey) {
		Object object = getSqlSessionTemplate().selectOne(
				getFindByPrimaryKeyQuery(), primaryKey);
		return object;
	}
	
 	
	//鍒犻櫎瀵硅薄杩斿洖INT锛堝垬鏂囪緣 2010-06-01锛�
	public int delete(final String statement, final Object parameter) {
		return getSqlSessionTemplate().delete(statement, parameter);
	}
	
	public void deleteById(PK id) {
		getSqlSessionTemplate().delete(getDeleteQuery(), id);
	}
	
	//鏂板瀵硅薄杩斿洖INT锛堝垬鏂囪緣 2010-06-01锛�
	public int save(final String statement, final Object parameter) {
		return getSqlSessionTemplate().insert(statement,
				parameter);
	}
	//鏂板瀵硅薄杩斿洖INT锛坆zq 2010-06-11锛�
	public int update(final String statement, final Object parameter) {
		return getSqlSessionTemplate().update(statement,
				parameter);
	}	
	public void save(E entity) {
		prepareObjectForSaveOrUpdate(entity);
		Object primaryKey = getSqlSessionTemplate().insert(getInsertQuery(),
				entity);
	}

	//鎵归噺鎻掑叆
	public void batchInsert(final  List list) {//
        try {
            if (list != null) {
                 
               this.getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
                   public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
                      try {
						executor.startBatch();
						  for (int i = 0, n = list.size(); i < n; i++) {
						     // executor.insert(getInsertQuery(), list.get(i));
							  sqlSessionFactory.openSession().insert(getInsertQuery(),list.get(i));							  
						      if(i % 1000 ==0){
						    	  executor.executeBatch();
						      }
						      
						  }						 
						  executor.executeBatch();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}  
                     
                      return null;
                   }
               });
            }
        } catch (Exception e) {
            if (log.isDebugEnabled()) {
               e.printStackTrace();
               log.fatal("batchInsert error: id [" + getInsertQuery() + "], parameterObject ["+ list + "].  Cause: "+ e.getMessage());
            }
        }
  
     }
	
	
	public List getList(final String statement, final Object parameter) {
		List list = getSqlSessionTemplate().selectList(statement, parameter);
		return list;
	}

	
	public void update(E entity) {
		prepareObjectForSaveOrUpdate(entity);
		Object primaryKey = getSqlSessionTemplate().update(getUpdateQuery(),
				entity);
	}

	/**
	 * 鐢ㄤ簬瀛愮被瑕嗙洊,鍦╥nsert,update涔嬪墠璋冪敤
	 * 
	 * @param o
	 */
	protected void prepareObjectForSaveOrUpdate(E o) {
	}

	public String getFindByPrimaryKeyQuery() {
		return getEntityClass().getSimpleName() + ".getById";
	}

	public String getInsertQuery() {
		return getEntityClass().getSimpleName() + ".insert";
	}

	public String getUpdateQuery() {
		return getEntityClass().getSimpleName() + ".update";
	}

	public String getDeleteQuery() {
		return getEntityClass().getSimpleName() + ".delete";
	}

	public String getCountQuery() {
		return getEntityClass().getSimpleName() + ".count";
	}
	/**鏌ヨ鎵�湁*/
	public String getFindAllQuery() {
		return getEntityClass().getSimpleName() + ".findAll";
	}
	/**鏌ヨ鍒楄〃杩斿洖List*/
	public String getFindListQuery() {
		return getEntityClass().getSimpleName() + ".findList";
	}
	
	public String getCallQuery() {
		return getEntityClass().getSimpleName() + ".callStatic";
	}
		
	
	
	protected Page pageQuery(String statementName, PageRequest pageRequest) {

		Number totalCount = (Number) this.getSqlSessionTemplate().selectOne(
				getCountQuery(), pageRequest.getFilters());
		if (totalCount == null || totalCount.intValue() <= 0) {
			return new Page(pageRequest, 0);
		}

		Page page = new Page(pageRequest, totalCount.intValue());

		// 鍏跺畠鍒嗛〉鍙傛暟,鐢ㄤ簬涓嶅枩娆㈡垨鏄洜涓哄吋瀹规�鑰屼笉浣跨敤鏂硅█(Dialect)鐨勫垎椤电敤鎴蜂娇鐢�
		// 涓巊etSqlMapClientTemplate().queryForList(statementName,
		// parameterObject)閰嶅悎浣跨敤
		Map filters = new HashMap();
		filters.put("offset", page.getFirstResult());
		filters.put("pageSize", page.getPageSize());
		filters.put("lastRows", page.getFirstResult() + page.getPageSize());
		filters.put("sortColumns", pageRequest.getSortColumns());

		// 娣峰悎涓や釜filters涓轰竴涓猣ilters,MapAndObject.get()鏂规硶灏嗗湪涓や釜瀵硅薄鍙栧�,Map濡傛灉鍙栧�涓簄ull,鍒欏啀鍦˙ean涓彇鍊�
		if (pageRequest.getFilters() instanceof Map) {
			filters.putAll((Map) pageRequest.getFilters());
		} else {
			Map parameterObject = BeanUtils.describe(pageRequest.getFilters());
			filters.putAll(parameterObject);
		}

		List list = getSqlSessionTemplate().selectList(statementName, filters,
				page.getFirstResult(), page.getPageSize());
		page.setResult(list);
		return page;
	}
	/**
	 * 鑷繁瀹氫箟瀹炵幇鍒嗛〉鏌ヨ
	 * @param statementName 鏌ヨ鏁版嵁SQL
	 * @param pageRequest
	 * @param countSql  鏌ヨ鍒嗛〉鎬昏褰曟暟 sql 
	 * @author bzq add
	 * @return
	 */
	protected Page pageQuery(String statementName,String countSql, PageRequest pageRequest) {
		//System.out.println("@@@ "+countSql);
		Number totalCount = (Number) getSqlSessionTemplate().selectOne(countSql,pageRequest.getFilters());
		if (totalCount == null || totalCount.intValue() <= 0) {
			return new Page(pageRequest, 0);
		}
		//System.out.println("@@@ "+totalCount);
		Page page = new Page(pageRequest, totalCount.intValue());

		// 鍏跺畠鍒嗛〉鍙傛暟,鐢ㄤ簬涓嶅枩娆㈡垨鏄洜涓哄吋瀹规�鑰屼笉浣跨敤鏂硅█(Dialect)鐨勫垎椤电敤鎴蜂娇鐢�
		// 涓巊etSqlMapClientTemplate().queryForList(statementName,
		// parameterObject)閰嶅悎浣跨敤
		Map filters = new HashMap();
		filters.put("offset", page.getFirstResult());
		filters.put("pageSize", page.getPageSize());
		filters.put("lastRows", page.getFirstResult() + page.getPageSize());
		filters.put("sortColumns", pageRequest.getSortColumns());

		// 娣峰悎涓や釜filters涓轰竴涓猣ilters,MapAndObject.get()鏂规硶灏嗗湪涓や釜瀵硅薄鍙栧�,Map濡傛灉鍙栧�涓簄ull,鍒欏啀鍦˙ean涓彇鍊�
		if (pageRequest.getFilters() instanceof Map) {
			filters.putAll((Map) pageRequest.getFilters());
		} else {
			Map parameterObject = cn.org.rapid_framework.beanutils.BeanUtils.describe(pageRequest.getFilters());
			filters.putAll(parameterObject);
		}

		List list = getSqlSessionTemplate().selectList(statementName, filters,
				page.getFirstResult(), page.getPageSize());
		page.setResult(list);
		return page;
	}

	/** 
	* <p>鏌ヨ鏁版嵁<br>
	* @param Map map
	* @return List 
	* @author bzq add
	*/
	public List findList(Map map) {
		List list = getSqlSessionTemplate().selectList(getFindListQuery(), map);
		return list;
	}
	 
	
	public void callOrderStatic(Map map){
		//sqlSessionFactory.openSession().
		getSqlSessionTemplate().update(getCallQuery(), map);
		
	}
	
	/** 
	* <p>鏌ヨ鎵�湁鏁版嵁<br>
	* @return List 
	* @author bzq update
	*/
	public List findAll() {
		List list = getSqlSessionTemplate().selectList(getFindAllQuery(), null);
		return list;
	}
/**
	public List findAll() {
		List list = getSqlSessionTemplate().selectList(getFindAllQuery(), null);
		return list;
	}	
	*/
	public boolean isUnique(E entity, String uniquePropertyNames) {
		throw new UnsupportedOperationException();
	}

	public void flush() {
		// ignore
	}

	public static class SqlSessionTemplate {
		SqlSessionFactory sqlSessionFactory;

		public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
			this.sqlSessionFactory = sqlSessionFactory;
		}

		public Object execute(SqlSessionCallback action) {
			SqlSession session = null;
			try {
				session = sqlSessionFactory.openSession();
				Object result = action.doInSession(session);
				return result;
			} finally {
				if (session != null)
					session.close();
			}
		}

		public Object selectOne(final String statement, final Object parameter) {
			return execute(new SqlSessionCallback() {
				public Object doInSession(SqlSession session) {
					return session.selectOne(statement, parameter);
				}
			});
		}

		public List selectList(final String statement, final Object parameter,
				final int offset, final int limit) {
			return (List) execute(new SqlSessionCallback() {
				public Object doInSession(SqlSession session) {
					return session.selectList(statement, parameter,
							new RowBounds(offset, limit));
				}
			});
		}
		
		//姝ゆ柟娉曚负娼樺僵铏�010-5-26鍐�
		public List selectList(final String statement, final Object parameter) {
			return (List) execute(new SqlSessionCallback() {
				public Object doInSession(SqlSession session) {
					return session.selectList(statement, parameter);
				}
			});
		}

		public int delete(final String statement, final Object parameter) {
			return (Integer) execute(new SqlSessionCallback() {
				public Object doInSession(SqlSession session) {
					return session.delete(statement, parameter);
				}
			});
		}

		public int update(final String statement, final Object parameter) {
			return (Integer) execute(new SqlSessionCallback() {
				public Object doInSession(SqlSession session) {
					return session.update(statement, parameter);
				}
			});
		}

		public int insert(final String statement, final Object parameter) {
			return (Integer) execute(new SqlSessionCallback() {
				public Object doInSession(SqlSession session) {
					return session.insert(statement, parameter);
				}
			});
		}
	}
	
	
	/**
	 * author      :  闄堜功鍗�  
	 * create time : Jun 29, 2010;
	 * modify time : Jun 29, 2010;
	 * return      : String;
	 * 鏌ヨ搴忓垪鐨勫�
	 */

	public String findId(String statement) {
		String id=null;
		try{
			id=(String)this.getSqlSessionTemplate().selectOne(statement,null);
		}catch(Exception e){
			e.printStackTrace();
		}
		return id;
	}
	

	 public   String createTaskID(){
	      java.text.SimpleDateFormat format =
	       new java.text.SimpleDateFormat("yyMMddHHmm");  //鐢ㄦ潵褰㈡垚瑙勮寖鐨勬棩鏈熸牸寮�
	       String curr_time = format.format(new java.util.Date(System.currentTimeMillis()));
	      seq++;
	      if(seq>=100){
	        seq = 10;
	      }
	        
	      return curr_time+String.valueOf(seq);
	 }
	 
	
	public static interface SqlSessionCallback {

		public Object doInSession(SqlSession session);

	}
	


}
